﻿using System.Xml;
using System.Collections.Generic;
using WMM.Tapioca.Taxonomy;
using System.Xml.Linq;
using WMM.Tapioca.Utilities;

namespace WMM.Tapioca.Linkbase
{
	/// <summary>
    /// XBRL 2.1 Specification 3.5.3.7 
    /// Locators are child elements of an extended link that point to resources external to the extended link itself. 
    /// All XBRL extended links MAY contain locators.
	/// </summary>
    public class Locator : ExtendedLinkElement, IIndexable
	{
        int IIndexable.Id
        {
            get { return GetHashCode(); }
        }

        int IIndexable.Name
        {
            get { return Label.GetHashCode(); }
        }

        //private Concept concept;

        /// <summary>
        /// A convenient *scratch variable* for our algorithm to use.
        /// </summary>
        private int inDegree; 

        public int InDegree
        {
            get
            {
                return inDegree;
            }
            set
            {
                inDegree = value;
            }
        }

        /// <summary>
        /// The out-bound Arcs of this Locator.
        /// </summary>
        private LinkedList<Arc> outArcs; 

        public LinkedList<Arc> OutArcs
        {
            get
            {
                return outArcs;
            }
            set
            {
                outArcs = value;
            }
        }

        /// <summary>
        /// The in-bound Arcs of this Locator.
        /// </summary>
        private LinkedList<Arc> inArcs; 

        public LinkedList<Arc> InArcs
        {
            get
            {
                return inArcs;
            }
            set
            {
                inArcs = value;
            }
        }

		/// <summary>
		/// The hyperlink reference defined by this locator.
		/// </summary>
		public string Href
		{
			get;
			private set;
		}


		/// <summary>
		/// The document URI for the locator's hyperlink reference.
		/// </summary>		
		public string HrefDocumentUri
		{
			get;
			private set;
		}

		/// <summary>
		/// The resource ID for the locator's hyperlink reference.
		/// </summary>		
		public string HrefResourceId
		{
			get;
			private set;
		}


		internal Locator(XElement locatorElement) 
		{
			foreach (XAttribute currentAttribute in locatorElement.Attributes())
			{
                if (!currentAttribute.Name.NamespaceName.Equals("http://www.w3.org/1999/xlink"))
                {
                    continue;
                }

				if (currentAttribute.Name.LocalName.Equals("href"))
				{
					this.Href = currentAttribute.Value;
					ParseHref();
				}
				else if (currentAttribute.Name.LocalName.Equals("label"))
					this.Label = currentAttribute.Value;
				else if (currentAttribute.Name.LocalName.Equals("title"))
					this.Title = currentAttribute.Value;
                else if (currentAttribute.Name.LocalName.Equals("role"))
                    this.Role = currentAttribute.Value;
			}

            InDegree = 0;
            OutArcs = new LinkedList<Arc>();
            InArcs = new LinkedList<Arc>();
		}


		private void ParseHref()
		{
			//string[] hrefSplit = this.Href.Split(new char[] { '#' });
            string[] hrefSplit = System.Web.HttpUtility.UrlDecode(this.Href).Split(new char[] { '#' });

			this.HrefDocumentUri = hrefSplit[0];

            if (hrefSplit.Length > 1)
            {
                this.HrefResourceId = hrefSplit[1];
            }
		}


        /// <returns> false </returns>
        public override bool IsLocator()
        {
            return true;
        }


        /// <returns> true </returns>
        public override bool IsResource()
        {
            return false;
        }


        public override int GetHashCode()
        {
            int hash = 1;
            hash = hash * 31 + (HrefDocumentUri != null ? HrefDocumentUri.GetHashCode() : 0);
            hash = hash * 31 + (HrefResourceId != null ? HrefResourceId.GetHashCode() : 0);
            hash = hash * 31 + Label.GetHashCode();
            return hash;
        }
	}
}
